<?php
/*
  Description

  This is a simple template engine. As template language used php
  itself with one different: we have postprocessing {$var} constuctions
  before output. Just for compact code:

        <title>{$title}</title>

                 vs

        <title><?php echo {$title} ?></title>

  In other ist clean php. Control structures:

        <?php if ($expr) {?>
            abc
        <?php } else { ?>
            <a href="abc">abc</a>
        <?php } ?>

  Require:

        <?php require 'path_to_template_elem' ?>

  etc

*/

class TemplateExecutor {

	private $templatesDir;

    /**
	 * @param String $templatesDir path to templates
	 */
	function __construct($templatesDir) {
	    Dir::checkExistsAndReadable($templatesDir);
	    $this->templatesDir = Dir::addEndslash(realpath($templatesDir));
	}

	private $hTemplateVars = array();
	public function assign($varName, $varValue) {
		$this->hTemplateVars[$varName] = $varValue;
	}

	public function assignArray(array $hValues) {
		foreach ($hValues as $varName => $varValue) {
			$this->hTemplateVars[$varName] = $varValue;
		}
	}

	public function getContent($templateFilename) {

		$templatePath= $this->templatesDir . $templateFilename;
		File::checkExistsAndReadable($templatePath);

		extract($this->hTemplateVars);

		ob_start();
		require $templatePath;
		$content = ob_get_contents();
		ob_clean();

		return $this->stupidReplaceTemplateVars($content);
	}

	public function getVar($name) {

	    if (!isset($this->hTemplateVars[$name])) {
	        return  "'$name' is not assigned";
	    }

	    if (is_array($this->hTemplateVars[$name]) || is_object($this->hTemplateVars[$name])) {
            return  "'$name' is composite";
	    }

	    return $this->hTemplateVars[$name];
	}

	private function stupidReplaceTemplateVars($content) {
        return preg_replace_callback('~\{\$([^}]+)\}~', array($this, 'doReplaceVar'), $content);
	}

	private function doReplaceVar(array $arrMatches) {
	    return $this->getVar($arrMatches[1]);
	}

    public function exec($templateFilename) {
        echo $this->getContent($templateFilename);
    }

    public function execCustom($filename, $position = 0) {

        $fp = fopen($filename, 'r');
        fseek($fp, $position);
        $code = stream_get_contents($fp);

        extract($this->hTemplateVars);

        ob_start();
        eval($code);
        $content = ob_get_contents();
        ob_clean();

        echo $this->stupidReplaceTemplateVars($content);
    }
}

?>
